/** 
 * 构建生产环境资源 
 * 示例： npm run build -- dongls
 * 这里会读取名为dongls的配置文件，根据配置构建  注意-- 和 dongls 之间存在空格 
 * @author dongls 
 */
/* util */
const fs = require('fs')
const path = require('path')
const shell = require('shelljs')
/* util */
const { stringify } = require('./util/string')
const { notificationEnd } = require('./util/notification')
/* webpack */
const webpack = require('webpack')
const webpackDefaultProductionConfig = require('../config/webpack.prod.conf')
/* model */
const { MONITOR_SCRIPT } = require('./model/const')
const BuildOption = require('./model/BuildOption')
// 监控监本
const monitorScript = MONITOR_SCRIPT

async function productionBuild(webpackConfigData, buildOption) {  
  
  let webpackConfig = webpackConfigData || webpackDefaultProductionConfig
  
  if (buildOption.isCloudBuild) {
    delete webpackConfig.cache
  }
  
  // 编译
  webpack(webpackConfig, async function (err, stats) {
    // 异常
    if (err) throw err
    
    process.stdout.write(`${stats.toString({
      colors: true,
      modules: false,
      children: false,
      chunks: false,
      chunkModules: false
    }) }\n`)
    
    if (!buildOption) {
      buildOption = new BuildOption()
    }
    
    // 服务端构建，切换web-resource仓库分支
    if (buildOption.isCloudBuild) {
      checkoutBranchWithWebResourceRepository(buildOption)
    }
    
    // 读取html生成 jsp
    await genJSP(path.resolve(__dirname, '../dist'), buildOption)
    // 复制静态资源
    copyResource(buildOption)
    
    // 服务端构建，提交代码到web-resource仓库
    if (buildOption.isCloudBuild) {
      commitCodeWithWebResourceRepository(buildOption)
    }
    
    notificationEnd()
    
  })
}

function copyResource(buildOption) {
  let targetPath = `${buildOption.path}/pc-fe-static`;
  let originPath = path.resolve(__dirname, '../public/resource/pc-fe-static');
  
  shell.rm('-rf', targetPath);
  shell.mkdir('-p', targetPath);
  shell.cp('-r', `${originPath}/*`, targetPath);
  
  console.log(`copy resource => ${targetPath}`)
}

async function genJSP(directory, buildOption) {
  let files = fs.readdirSync(directory);
  // 过滤html
  let htmls = files.filter(file => file.endsWith('.html'));
  
  // 生成jsp
  let microTask = htmls.map(html => gen(directory, html, buildOption));
  
  await Promise.all(microTask);
  
  // 复制文件
  let distOriginPath = path.resolve(__dirname, '../dist');
  let distTargetPath = `${buildOption.path}/pc-fe`;
  let jspTargetPath = `${buildOption.path}/dist`;
  
  // 是否为全量构建
  let isFullBuild = buildOption.isFullBuild
  // 复制jsp
  isFullBuild && shell.rm('-rf', jspTargetPath);
  shell.mkdir('-p', jspTargetPath);
  shell.cp('-r', `${distOriginPath}/jsp/*`, jspTargetPath);
  // 清空jsp
  shell.rm('-rf', `${distOriginPath}/jsp`);
  
  // 复制静态资源
  isFullBuild && shell.rm('-rf', distTargetPath);
  shell.mkdir('-p', distTargetPath);
  shell.cp('-r', `${distOriginPath}/*`, distTargetPath);
  
  console.log(`build on ${new Date().toLocaleString()}`)
}

function gen(directory, fileName, buildOption) {
  return new Promise((resolve, reject) => {
    let jspName = `${fileName.substring(0, fileName.lastIndexOf('.'))}.jsp`;
    
    // 1.读取html
    fs.readFile(path.resolve(directory, fileName), (err, data) => {
      if (err) reject(err)
      let template = data.toString();
      
      // 2.生成jsp内容
      // #{} => ${}
      template = template.replace(/#\{(.*?)\}/g, '${$1}')
      // 注入jsp头部信息
      template = `<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>\n${template}`
      // 注入构建信息
      template += `\n<!-- build on ${new Date().toLocaleString()}. -->`
      // 注入构建配置信息
      template += `\n<!-- build of ${stringify(buildOption)}. -->`
      // 注入监控脚本
      template = template.replace('</head>', `${monitorScript}</head>`)
      
      let dirPath = path.resolve(directory, 'jsp');
      
      if (!existsSync(dirPath)) {
        fs.mkdirSync(dirPath)
      }
      
      // 3.写入文件
      fs.writeFile(path.resolve(dirPath, jspName), template, () => {
        if (err) reject(err);
        resolve();
      })
      
    })
    
  })
}

function checkoutBranchWithWebResourceRepository(buildOption) {
  // web-resource仓库地址
  const webResourceRepositoryPath = buildOption.path
  const branch = buildOption.branch
  
  if (!branch) {
    console.error('【ERROR】Caused: branch is empty')
    process.exitCode = 1
    process.exit()
  }
  
  shell.cd(webResourceRepositoryPath)
  
  shell.exec('git checkout .')
  shell.exec('git stash')
  shell.exec('git checkout master')
  shell.exec('git fetch -p')
  shell.exec(`git branch -D ${branch}`)
  shell.exec(`git checkout ${branch}`)
  
  console.log(`checkout branch => ${branch}`)
  console.log(`checkout branch on ${new Date().toLocaleString()}`)
  console.log('web-resource 仓库分支列表')
  
  shell.exec('git branch')
}

/** 
 * @description 提交代码到web-resource仓库
 * @param {BuildOption} buildOption 构建配置
*/
function commitCodeWithWebResourceRepository(buildOption) {
  // web-resource仓库地址
  const webResourceRepositoryPath = buildOption.path
  
  shell.cd(webResourceRepositoryPath)
  
  shell.exec('git add --all')
  shell.exec('git add .')
  shell.exec(`git commit -am "build: ${buildOption.branch} 分支 构建前端资源 "`)
  shell.exec('git push')
  
  shell.exec('sleep 10')
}

function existsSync(pathName) {
  try {
    fs.accessSync(pathName, fs.F_OK);
  } catch (e) {
    return false;
  }
  return true;
}

exports.productionBuild = productionBuild
